package service

import (
	"crypto/rsa"
	"regexp"

	"github.com/dgrijalva/jwt-go"
)

var (
	privKey *rsa.PrivateKey
	pubKey  *rsa.PublicKey
)

type (
	JwtPayload struct {
		Mobile   string `json:"mobile"`
		Email    string `json:"email"`
		GID      string `json:"g_id"`
		UserName string `json:"user_name"`
	}

	loginClaims struct {
		jwt.StandardClaims
		*JwtPayload
	}
)

// ExtractToken 提取 token
func ExtractToken(token string) string {
	reg, _ := regexp.Compile(`^[bB]earer (([a-zA-z0-9\-_]+\.){2}[a-zA-z0-9\-_]+)$`)
	authReg := reg.FindStringSubmatch(token)
	if len(authReg) != 3 {
		return token
	}
	return authReg[1]
}

// LoadPubKey 加载公钥
func LoadPubKey(key string) func() {
	return func() {
		pubKey, _ = jwt.ParseRSAPublicKeyFromPEM([]byte(key))
	}
}

// LoadPrivKey 加载私钥
func LoadPrivKey(key string) func() {
	return func() {
		privKey, _ = jwt.ParseRSAPrivateKeyFromPEM([]byte(key))
	}
}

// VerifyJwtToken jwt token 校验
func VerifyJwtToken(tokenStr string) (*JwtPayload, error) {
	parse := &jwt.Parser{
		ValidMethods:         nil,
		UseJSONNumber:        false,
		SkipClaimsValidation: true,
	}
	token, err := parse.ParseWithClaims(tokenStr, &loginClaims{}, func(token *jwt.Token) (i interface{}, e error) {
		return pubKey, nil
	})
	if err != nil {
		return nil, err
	}
	claims := token.Claims.(*loginClaims)
	err = claims.Valid()
	if err != nil {
		return nil, err
	}
	return claims.JwtPayload, nil
}

// GenJwtToken jwt token 生成
func GenJwtToken(payload *JwtPayload, issuedAt, expiredAt int64) (string, error) {
	t := jwt.New(jwt.SigningMethodRS256)
	t.Claims = &loginClaims{
		StandardClaims: jwt.StandardClaims{
			ExpiresAt: expiredAt,
			IssuedAt:  issuedAt,
		},
		JwtPayload: payload,
	}
	return t.SignedString(privKey)
}
